package org.dfzt.modules.online.cgreport.service.impl;

import cn.hutool.core.util.ReUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.dfzt.common.api.vo.Result;
import org.dfzt.common.exception.SpringBootException;
import org.dfzt.common.system.service.ISysBaseAPI;
import org.dfzt.common.system.query.QueryGenerator;
import org.dfzt.common.system.vo.DynamicDataSourceModel;
import org.dfzt.common.util.dynamic.db.DataSourceCachePool;
import org.dfzt.common.util.dynamic.db.DynamicDBUtil;
import org.dfzt.common.util.dynamic.db.SqlUtils;
import org.dfzt.common.util.oConvertUtils;
import org.dfzt.modules.online.cgreport.entity.OnlCgreportHead;
import org.dfzt.modules.online.cgreport.entity.OnlCgreportItem;
import org.dfzt.modules.online.cgreport.entity.OnlCgreportParam;
import org.dfzt.modules.online.cgreport.mapper.OnlCgreportHeadMapper;
import org.dfzt.modules.online.cgreport.model.OnlCgreportModel;
import org.dfzt.modules.online.cgreport.service.IOnlCgreportHeadService;
import org.dfzt.modules.online.cgreport.service.IOnlCgreportItemService;
import org.dfzt.modules.online.cgreport.service.IOnlCgreportParamService;
import org.dfzt.modules.online.cgreport.util.SqlUtil;
import org.dfzt.modules.online.config.util.d;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("onlCgreportHeadServiceImpl")
public class OnlCgreportHeadServiceImpl extends ServiceImpl<OnlCgreportHeadMapper, OnlCgreportHead>
  implements IOnlCgreportHeadService {
  private static final Logger a = LoggerFactory.getLogger(OnlCgreportHeadServiceImpl.class);

  
  @Autowired
  private IOnlCgreportParamService onlCgreportParamService;

  
  @Autowired
  private IOnlCgreportItemService onlCgreportItemService;

  
  @Autowired
  private OnlCgreportHeadMapper mapper;
  
  @Autowired
  private ISysBaseAPI sysBaseAPI;

  
  @Override
  public Map<String, Object> executeSelectSql(String sql, String onlCgreportHeadId, Map<String, Object> params) throws SQLException {
    String str1 = this.sysBaseAPI.getDatabaseType();
    
    LambdaQueryWrapper<OnlCgreportParam> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
    lambdaQueryWrapper1.eq(OnlCgreportParam::getCgrheadId, onlCgreportHeadId);
    List<OnlCgreportParam> list1 = this.onlCgreportParamService.list(lambdaQueryWrapper1);
    if (list1 != null && list1.size() > 0) {
      for (OnlCgreportParam onlCgreportParam : list1) {
        
        Object object1 = params.get("self_" + onlCgreportParam.getParamName());
        String str = "";
        if (object1 != null) {
          str = object1.toString();
        } else if (object1 == null && oConvertUtils.isNotEmpty(onlCgreportParam.getParamValue())) {
          str = onlCgreportParam.getParamValue();
        } 
        sql = sql.replace("${" + onlCgreportParam.getParamName() + "}", str);
      } 
    }
    HashMap hashMap = new HashMap();
    
    Integer integer1 = Integer.valueOf(oConvertUtils.getInt(params.get("pageSize"), 10));
    Integer integer2 = Integer.valueOf(oConvertUtils.getInt(params.get("pageNo"), 1));
    Page page = new Page(integer2.intValue(), integer1.intValue());
    
    LambdaQueryWrapper<OnlCgreportItem> lambdaQueryWrapper2 = new LambdaQueryWrapper();
    lambdaQueryWrapper2.eq(OnlCgreportItem::getCgrheadId, onlCgreportHeadId);
    lambdaQueryWrapper2.eq(OnlCgreportItem::getIsSearch, Integer.valueOf(1));
    List list2 = this.onlCgreportItemService.list(lambdaQueryWrapper2);
    
    String str2 = "jeecg_rp_temp.";
    String str3 = org.dfzt.modules.online.cgreport.util.a.a(list2, params, str2);

    
    if (ReUtil.contains(" order\\s+by ", sql.toLowerCase()) && 
      "SQLSERVER".equalsIgnoreCase(str1)) {
      throw new SpringBootException("SqlServer不支持SQL内排序!");
    }

    
    String str4 = "select * from (" + sql + ") jeecg_rp_temp  where 1=1 " + str3;
    
    str4 = SqlUtil.b(str4);
    Object object = params.get("column");
    if (object != null) {
      str4 = str4 + " order by jeecg_rp_temp." + object.toString() + " " + params.get("order").toString();
    }
    
    a.info("报表查询sql=>\r\n" + str4);
    IPage iPage = this.mapper.selectPageBySql(page, str4);
    hashMap.put("total", Long.valueOf(iPage.getTotal()));
    
    hashMap.put("records", org.dfzt.modules.online.cgform.util.b.d(iPage.getRecords()));
    return hashMap;
  }







  
  @Override
  public Map<String, Object> executeSelectSqlDynamic(String dbKey, String sql, Map<String, Object> params, String onlCgreportHeadId) {
    DynamicDataSourceModel dynamicDataSourceModel = DataSourceCachePool.getCacheDynamicDataSourceModel(dbKey);
    
    String str1 = (String)params.get("order");
    String str2 = (String)params.get("column");
    int i = oConvertUtils.getInt(params.get("pageNo"), 1);
    int j = oConvertUtils.getInt(params.get("pageSize"), 10);
    a.info("【Online多数据源逻辑】报表查询参数params: " + JSON.toJSONString(params));


    
    LambdaQueryWrapper<OnlCgreportParam> lambdaQueryWrapper1 = new LambdaQueryWrapper();
    lambdaQueryWrapper1.eq(OnlCgreportParam::getCgrheadId, onlCgreportHeadId);
    List<OnlCgreportParam> list1 = this.onlCgreportParamService.list(lambdaQueryWrapper1);
    if (list1 != null && list1.size() > 0) {
      for (OnlCgreportParam onlCgreportParam : list1) {
        
        Object object1 = params.get("self_" + onlCgreportParam.getParamName());
        String str = "";
        if (object1 != null) {
          str = object1.toString();
        } else if (object1 == null && oConvertUtils.isNotEmpty(onlCgreportParam.getParamValue())) {
          str = onlCgreportParam.getParamValue();
        } 
        sql = sql.replace("${" + onlCgreportParam.getParamName() + "}", str);
      } 
    }

    
    LambdaQueryWrapper<OnlCgreportItem> lambdaQueryWrapper2 = new LambdaQueryWrapper();
    lambdaQueryWrapper2.eq(OnlCgreportItem::getCgrheadId, onlCgreportHeadId);
    lambdaQueryWrapper2.eq(OnlCgreportItem::getIsSearch, Integer.valueOf(1));
    List list2 = this.onlCgreportItemService.list(lambdaQueryWrapper2);

    
    if (ReUtil.contains(" order\\s+by ", sql.toLowerCase()) && 
      "3".equalsIgnoreCase(dynamicDataSourceModel.getDbType())) {
      throw new SpringBootException("SqlServer不支持SQL内排序!");
    }

    
    String str3 = "jeecg_rp_temp.";
    String str4 = org.dfzt.modules.online.cgreport.util.a.a(list2, params, str3);
    String str5 = "select * from (" + sql + ") jeecg_rp_temp  where 1=1 " + str4;
    
    str5 = SqlUtil.b(str5);

    
    String str6 = SqlUtils.getCountSql(str5);

    
    Object object = params.get("column");
    if (object != null) {
      str5 = str5 + " order by jeecg_rp_temp." + object.toString() + " " + params.get("order").toString();
    }

    
    String str7 = SqlUtils.createPageSqlByDBType(dynamicDataSourceModel.getDbType(), str5, i, j);

    
    a.info("多数据源 报表查询sql=>querySql: " + str5);
    a.info("多数据源 报表查询sql=>pageSQL: " + str7);
    a.info("多数据源 报表查询sql=>countSql: " + str6);
    
    HashMap hashMap = new HashMap();
    
    Map map = (Map)DynamicDBUtil.findOne(dbKey, str6, new Object[0]);
    hashMap.put("total", map.get("total"));
    
    List list3 = DynamicDBUtil.findList(dbKey, str7, new Object[0]);
    hashMap.put("records",  org.dfzt.modules.online.cgform.util.b.d(list3));
    return hashMap;
  }


  
  @Override
  @Transactional(rollbackFor = {Exception.class})
  public Result<?> editAll(OnlCgreportModel values) {
    OnlCgreportHead onlCgreportHead1 = values.getHead();
    
    OnlCgreportHead onlCgreportHead2 = (OnlCgreportHead)getById(onlCgreportHead1.getId());
    if (onlCgreportHead2 == null) {
      return Result.error("未找到对应实体");
    }
    
    updateById(onlCgreportHead1);



    
    LambdaQueryWrapper<OnlCgreportItem> lambdaQueryWrapper1 = new LambdaQueryWrapper();
    lambdaQueryWrapper1.eq(OnlCgreportItem::getCgrheadId, onlCgreportHead1.getId());
    this.onlCgreportItemService.remove(lambdaQueryWrapper1);
    
    LambdaQueryWrapper<OnlCgreportParam> lambdaQueryWrapper2 = new LambdaQueryWrapper();
    lambdaQueryWrapper2.eq(OnlCgreportParam::getCgrheadId, onlCgreportHead1.getId());
    this.onlCgreportParamService.remove(lambdaQueryWrapper2);

    
    for (OnlCgreportParam onlCgreportParam : values.getParams()) {
      onlCgreportParam.setCgrheadId(onlCgreportHead1.getId());
    }
    for (OnlCgreportItem onlCgreportItem : values.getItems()) {
      
      onlCgreportItem.setFieldName(onlCgreportItem.getFieldName().trim().toLowerCase());
      onlCgreportItem.setCgrheadId(onlCgreportHead1.getId());
    } 
    
    this.onlCgreportItemService.saveBatch(values.getItems());
    this.onlCgreportParamService.saveBatch(values.getParams());
    return Result.ok("全部修改成功");
  }



  
  @Override
  @Transactional(rollbackFor = {Exception.class})
  public Result<?> delete(String id) {
    boolean bool = removeById(id);
    if (bool) {
      
      LambdaQueryWrapper<OnlCgreportItem> lambdaQueryWrapper1 = new LambdaQueryWrapper();
      lambdaQueryWrapper1.eq(OnlCgreportItem::getCgrheadId, id);
      this.onlCgreportItemService.remove(lambdaQueryWrapper1);
      
      LambdaQueryWrapper<OnlCgreportParam> lambdaQueryWrapper2 = new LambdaQueryWrapper();
      lambdaQueryWrapper2.eq(OnlCgreportParam::getCgrheadId, id);
      this.onlCgreportParamService.remove(lambdaQueryWrapper2);
    } 
    return Result.ok("删除成功");
  }

  
  @Override
  @Transactional(rollbackFor = {Exception.class})
  public Result<?> bathDelete(String[] ids) {
    for (String str : ids) {
      boolean bool = removeById(str);
      if (bool) {
        
        LambdaQueryWrapper<OnlCgreportItem> lambdaQueryWrapper1 = new LambdaQueryWrapper();
        lambdaQueryWrapper1.eq(OnlCgreportItem::getCgrheadId, str);
        this.onlCgreportItemService.remove(lambdaQueryWrapper1);
        
        LambdaQueryWrapper<OnlCgreportParam> lambdaQueryWrapper2 = new LambdaQueryWrapper();
        lambdaQueryWrapper2.eq(OnlCgreportParam::getCgrheadId, str);
        this.onlCgreportParamService.remove(lambdaQueryWrapper2);
      } 
    } 
    return Result.ok("删除成功");
  }




  
  @Override
  public List<String> getSqlFields(String sql, String dbKey) throws SQLException {
    List list = null;
    if (StringUtils.isNotBlank(dbKey)) {
      list = a(sql, dbKey);
    } else {
      list = a(sql, null);
    } 
    return list;
  }





  
  @Override
  public List<String> getSqlParams(String sql) {
    if (oConvertUtils.isEmpty(sql)) {
      return null;
    }
    ArrayList arrayList = new ArrayList();
    String str = "\\$\\{\\w+\\}";
    
    Pattern pattern = Pattern.compile(str);
    Matcher matcher = pattern.matcher(sql);
    while (matcher.find()) {
      String str1 = matcher.group();
      arrayList.add(str1.substring(str1.indexOf("{") + 1, str1.indexOf("}")));
    } 
    return arrayList;
  }





  
  private List<String> a(String paramString1, String paramString2) throws SQLException {
    Set set;
    if (oConvertUtils.isEmpty(paramString1)) {
      return null;
    }

    
    paramString1 = paramString1.trim();
    if (paramString1.endsWith(";")) {
      paramString1 = paramString1.substring(0, paramString1.length() - 1);
    }

    
    paramString1 = QueryGenerator.convertSystemVariables(paramString1);

    
    paramString1 = SqlUtil.a(paramString1);



    
    if (StringUtils.isNotBlank(paramString2)) {
      a.info("parse sql : " + paramString1);
      DynamicDataSourceModel dynamicDataSourceModel = DataSourceCachePool.getCacheDynamicDataSourceModel(paramString2);
      
      if (ReUtil.contains(" order\\s+by ", paramString1.toLowerCase()) && 
        "3".equalsIgnoreCase(dynamicDataSourceModel.getDbType())) {
        throw new SpringBootException("SqlServer不支持SQL内排序!");
      }



      
      if ("1".equals(dynamicDataSourceModel.getDbType())) {
        paramString1 = "SELECT * FROM (" + paramString1 + ") temp LIMIT 1";
      } else if ("2".equals(dynamicDataSourceModel.getDbType())) {
        paramString1 = "SELECT * FROM (" + paramString1 + ") temp WHERE ROWNUM <= 1";
      } else if ("3".equals(dynamicDataSourceModel.getDbType())) {
        paramString1 = "SELECT TOP 1 * FROM (" + paramString1 + ") temp";
      } 
      a.info("parse sql with page : " + paramString1);
      Map map = (Map)DynamicDBUtil.findOne(paramString2, paramString1, new Object[0]);
      if (map == null) {
        throw new SpringBootException("该报表sql没有数据");
      }
      set = map.keySet();
    } else {
      a.info("parse sql: " + paramString1);
      
      if (ReUtil.contains(" order\\s+by ", paramString1.toLowerCase()) && 
        "SQLSERVER".equalsIgnoreCase(this.sysBaseAPI.getDatabaseType())) {
        throw new SpringBootException("SqlServer不支持SQL内排序!");
      }

      
      IPage iPage = this.mapper.selectPageBySql(new Page(1L, 1L), paramString1);
      List list = iPage.getRecords();
      if (list.size() < 1) {
        throw new SpringBootException("该报表sql没有数据");
      }
      set = ((Map)list.get(0)).keySet();
    } 

    
    if (set != null) {
      set.remove("ROW_ID");
    }
    return new ArrayList(set);
  }

  
  @Override
  public Map<String, Object> queryCgReportConfig(String reportId) {
    HashMap hashMap = new HashMap(0);
    Map map = this.mapper.queryCgReportMainConfig(reportId);
    List list1 = this.mapper.queryCgReportItems(reportId);
    List list2 = this.mapper.queryCgReportParams(reportId);
    
    if (d.a()) {
      hashMap.put("main", org.dfzt.modules.online.cgform.util.b.b(map));
      hashMap.put("items", org.dfzt.modules.online.cgform.util.b.d(list1));
    } else {
      hashMap.put("main", map);
      hashMap.put("items", list1);
    } 
    
    hashMap.put("params", list2);
    return hashMap;
  }





  
  @Override
  public List<Map<?, ?>> queryByCgReportSql(String sql, Map params, Map paramData, int pageNo, int pageSize) {
    String str = SqlUtil.a(sql, params);
    List list = null;
    
    if (paramData != null && paramData.size() == 0) {
      paramData = null;
    }
    if (pageNo == -1 && pageSize == -1) {
      list = this.mapper.executeSelete(str);
    } else {
      Page page = new Page(pageNo, pageSize);
      IPage iPage = this.mapper.selectPageBySql(page, str);
      if (iPage.getRecords() != null && iPage.getRecords().size() > 0) {
        list.addAll(iPage.getRecords());
      }
    } 
    return list;
  }
}
